/*
 * CommandLine.cs
 * 
 * Parses command line arguments to override fields in specified Settings object.
 */
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace Jitsu
{
    internal class CommandLine
    {
        private CommandLine() { }

        public static int ShowUsage()
        {
            Console.Error.WriteLine(@"Usage: [<filespec> <regex pattern> [/s] [/i] [/l] [/v] [/w=<width>] [/r=<replacement>]]");
            Console.Error.WriteLine(@"   filespec: the pattern of files to search");
            Console.Error.WriteLine(@"   regex pattern: the regular expression to search for");
            Console.Error.WriteLine(@"   /s: recurse Subdirectories");
            Console.Error.WriteLine(@"   /i: Ignore case");
            Console.Error.WriteLine(@"   /l: single-Line semantics ('.' doesn't match newline)");
            Console.Error.WriteLine(@"   /v: emulate Visual Studio's support for :i, :n, :q");
            Console.Error.WriteLine(@"   /w: set line-Wrapping width for output");
            Console.Error.WriteLine(@"   /r: Replace matches with the specified string - USE WITH CAUTION!");
            return 1;
        }

        public static void Parse(string[] args, Options options)
        {
            // All parameters are either /<switch>=<value> or just plain <text> format.
            Regex argpatt =
                new Regex(@"^( ([/\-](?<switch>[silvwr][\+\-]?)(=(?<value>.*))?) | (?<text>[^/\-].*) )$",
                RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);

            // Parse each argument, as either <text> or /<switch>=<value>.
            foreach (string arg in args)
            {
                if (!argpatt.IsMatch(arg))
                    throw new ApplicationException(String.Format("Unrecognized command line argument: {0}", arg));

                Match m = argpatt.Match(arg);

                if (m.Groups["text"].Value != String.Empty)
                {
                    if (options.FilePattern == null || options.BaseDirectory == null)
                    {
                        options.FilePattern = Path.GetFileName(arg);
                        options.BaseDirectory = Path.GetDirectoryName(arg);
                    }
                    else if (options.RegexPattern == null)
                    {
                        options.RegexPattern = arg;
                    }
                    else throw new ApplicationException(String.Format("Unrecognized command line argument: {0}", arg));
                }
                else if (m.Groups["switch"].Value != String.Empty)
                {
                    switch (m.Groups["switch"].Value[0])
                    {
                        case 's':
                            options.DoRecursion = (m.Groups["switch"].Value.EndsWith("-")) ? false : true;
                            break;
                        case 'i':
                            options.RegexIgnoreCase = (m.Groups["switch"].Value.EndsWith("-")) ? false : true;
                            break;
                        case 'l':
                            options.RegexSingleline = (m.Groups["switch"].Value.EndsWith("-")) ? false : true;
                            break;
                        case 'v':
                            options.RegexMimicVS = (m.Groups["switch"].Value.EndsWith("-")) ? false : true;
                            break;
                        case 'w':
                            options.OutputWidth = UInt16.Parse(m.Groups["value"].Value);
                            break;
                        case 'r':
                            options.ReplacementText = m.Groups["value"].Value;
                            break;
                        default: throw new ApplicationException(String.Format("Unrecognized command line argument: {0}", arg));
                    }
                }
            }//foreach

            // Validate required args and apply defaults.
            if (String.IsNullOrEmpty(options.RegexPattern))
                throw new ApplicationException("Must specify regex pattern.");

            if (String.IsNullOrEmpty(options.BaseDirectory))
                options.BaseDirectory = Environment.CurrentDirectory;

            if (String.IsNullOrEmpty(options.FilePattern))
                options.FilePattern = "*";
        }
    }
}